#include "cmd-plugins.h"

#include "console.h"
#include "debugger.h"
#include "module.h"
#include "plugin_loader.h"

static bool bScyllaLoaded = false;

static DWORD WINAPI scyllaThread(void* lpParam) {
  typedef INT(WINAPI * SCYLLASTARTGUI)(DWORD pid, HINSTANCE mod,
                                       DWORD_PTR entrypoint);
  SCYLLASTARTGUI ScyllaStartGui = 0;
  HINSTANCE hScylla = LoadLibraryW(L"Scylla.dll");
  if (!hScylla) {
    dputs(QT_TRANSLATE_NOOP("DBG", "Error loading Scylla.dll!"));
    bScyllaLoaded = false;
    return 0;
  }
  ScyllaStartGui = (SCYLLASTARTGUI)GetProcAddress(hScylla, "ScyllaStartGui");
  if (!ScyllaStartGui) {
    dputs(QT_TRANSLATE_NOOP(
        "DBG", "Could not find export 'ScyllaStartGui' inside Scylla.dll"));
    bScyllaLoaded = false;
    FreeLibrary(hScylla);
    return 0;
  }
  auto cip = GetContextDataEx(fdProcessInfo->hThread, UE_CIP);
  auto cipModBase = ModBaseFromAddr(cip);
  ScyllaStartGui(fdProcessInfo->dwProcessId, (HINSTANCE)cipModBase, cip);
  FreeLibrary(hScylla);
  bScyllaLoaded = false;
  return 0;
}

bool cbDebugStartScylla(int argc, char* argv[]) {
  if (bScyllaLoaded) {
    dputs(QT_TRANSLATE_NOOP("DBG", "Scylla is already loaded"));
    return false;
  }
  bScyllaLoaded = true;
  CloseHandle(CreateThread(0, 0, scyllaThread, 0, 0, 0));
  return true;
}

bool cbInstrPluginLoad(int argc, char* argv[]) {
  if (IsArgumentsLessThan(argc, 2)) return false;
  return pluginload(argv[1]);
}

bool cbInstrPluginUnload(int argc, char* argv[]) {
  if (IsArgumentsLessThan(argc, 2)) return false;
  return pluginunload(argv[1]);
}

bool cbInstrPluginReload(int argc, char* argv[]) {
  if (IsArgumentsLessThan(argc, 2)) return false;
  if (!pluginunload(argv[1])) return false;
  if (argc <= 2) {
    auto text = StringUtils::Utf8ToUtf16(GuiTranslateText(
        QT_TRANSLATE_NOOP("DBG", "Press OK to reload the plugin...")));
    auto title = StringUtils::Utf8ToUtf16(
        GuiTranslateText(QT_TRANSLATE_NOOP("DBG", "Reload")));
    MessageBoxW(GuiGetWindowHandle(), text.c_str(), title.c_str(), 0);
  }
  return pluginload(argv[1]);
}